package com.teejdeej.simpleneuralgame;

import java.util.ArrayList;
import java.util.List;

public class SightLines {
	private List<List<Integer>> m_sightLines;
	
	SightLines()
	{
		m_sightLines = new ArrayList<List<Integer>>();
		for(int a = 0; a < MainGame.NumberOfDirections; a++)
		{
			List<Integer> t_newList = new ArrayList<Integer>();
			m_sightLines.add(t_newList);
		}
	}
	
	public static SightLines generateSightLines(int[][] board, int[] position)
	{
		SightLines t_out = new SightLines();
		
		for(int a = 0; a < MainGame.NumberOfDirections; a++)
		{
			List<Integer> t_scanResults = new ArrayList<Integer>();
			int[] t_scanPosition = position.clone();
			
			switch(a)
			{
			case MainGame.DirectionUp:
				t_scanPosition[1]--;
			break;
			
			case MainGame.DirectionDown:
				t_scanPosition[1]++;
			break;
				
			case MainGame.DirectionLeft:
				t_scanPosition[0]--;
			break;
				
			case MainGame.DirectionRight:
				t_scanPosition[0]++;
			break;
			
			case MainGame.DirectionUpLeft:
				t_scanPosition[0]--;
				t_scanPosition[1]--;
			break;
			
			case MainGame.DirectionUpRight:
				t_scanPosition[0]++;
				t_scanPosition[1]--;
			break;
			
			case MainGame.DirectionDownLeft:
				t_scanPosition[0]--;
				t_scanPosition[1]++;
			break;
			
			case MainGame.DirectionDownRight:
				t_scanPosition[0]++;
				t_scanPosition[1]++;
			break;
			}
			
			int t_scanDistance = 0;
			
			while(t_scanDistance < MainGame.ScanDistance && t_scanPosition[0] >= 0 && t_scanPosition[0] < MainGame.ScreenWidth && t_scanPosition[1] >= 0 && t_scanPosition[1] < MainGame.ScreenHeight)
			{
				t_scanDistance++;
				t_scanResults.add(board[t_scanPosition[0]][t_scanPosition[1]]);
				
				switch(a)
				{
				case MainGame.DirectionUp:
					t_scanPosition[1]--;
				break;
				
				case MainGame.DirectionDown:
					t_scanPosition[1]++;
				break;
					
				case MainGame.DirectionLeft:
					t_scanPosition[0]--;
				break;
					
				case MainGame.DirectionRight:
					t_scanPosition[0]++;
				break;
				
				case MainGame.DirectionUpLeft:
					t_scanPosition[0]--;
					t_scanPosition[1]--;
				break;
				
				case MainGame.DirectionUpRight:
					t_scanPosition[0]++;
					t_scanPosition[1]--;
				break;
				
				case MainGame.DirectionDownLeft:
					t_scanPosition[0]--;
					t_scanPosition[1]++;
				break;
				
				case MainGame.DirectionDownRight:
					t_scanPosition[0]++;
					t_scanPosition[1]++;
				break;
				}
			}
			
			t_out.setDirection(a, t_scanResults);
		}
		
		return t_out;
	}
	
	public void setDirection(int direction, List<Integer> line)
	{
		m_sightLines.get(direction).clear();
		m_sightLines.get(direction).addAll(line);
	}
	
	public double[] getNeuralNetInput()
	{
		double[] t_input = new double[(MainGame.BoardPossibilities - 1) * MainGame.NumberOfDirections];
		
		for(int a = 0; a < m_sightLines.size(); a++)
		{
			int t_nearestEnemy = 0;
			int t_nearestProjectile = 0;
			int t_nearestWall = 0;
			
			for(int b = 0; b < m_sightLines.get(a).size(); b++)
			{
				switch(m_sightLines.get(a).get(b))
				{
				case MainGame.BoardEnemy:
					if(t_nearestEnemy == 0)
						t_nearestEnemy = b + 1;
				break;
				
				case MainGame.BoardProjectileEnemy:
					if(t_nearestProjectile == 0)
						t_nearestProjectile = b + 1;
				break;
				
				case MainGame.BoardWall:
					if(t_nearestWall == 0)
						t_nearestWall = b + 1;
				break;
				}
			}
			
			if(t_nearestEnemy == 0)
				t_input[a * (MainGame.BoardPossibilities - 1)] = 1.0;
			else
				t_input[a * (MainGame.BoardPossibilities - 1)] = (double) t_nearestEnemy / (double) MainGame.ScanDistance;
			
			if(t_nearestProjectile == 0)
				t_input[a * (MainGame.BoardPossibilities - 1) + 1] = 1.0;
			else
				t_input[a * (MainGame.BoardPossibilities - 1) + 1] = (double) t_nearestProjectile / (double) MainGame.ScanDistance;
			
			if(t_nearestWall == 0)
				t_input[a * (MainGame.BoardPossibilities - 1) + 2] = 1.0;
			else
				t_input[a * (MainGame.BoardPossibilities - 1) + 2] = (double) t_nearestWall / (double) MainGame.ScanDistance;
		}
		
		return t_input;
	}
}
